#    Copyright Brandon Stafford
#
#    This file is part of Pysolar.
#
#    Pysolar is free software; you can redistribute it and/or modify
#    it under the terms of the GNU General Public License as published by
#    the Free Software Foundation; either version 3 of the License, or
#    (at your option) any later version.
#
#    Pysolar is distributed in the hope that it will be useful,
#    but WITHOUT ANY WARRANTY; without even the implied warranty of
#    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
#    GNU General Public License for more details.
#
#    You should have received a copy of the GNU General Public License along
#    with Pysolar. If not, see <http://www.gnu.org/licenses/>.

"""This file contains functions related to time conversion.
"""
import warnings
import sys
import datetime
import time
from .constants import \
    seconds_per_day
from pysolar.tzinfo_check import check_aware_dt

julian_day_offset = 1721425 - 0.5 # add to datetime.datetime.toordinal() to get Julian day number
gregorian_day_offset = 719163 # number of days to add to datetime.datetime.timestamp() / seconds_per_day to agree with datetime.datetime.toordinal()
tt_offset = 32.184 # seconds to add to TAI to get TT

#+
# Table of leap-seconds (to date) taken from Wikipedia
# <https://en.wikipedia.org/wiki/Leap_second>.
#-
leap_seconds_base_year = 1972
leap_seconds_adjustments = \
    [ # two entries per year starting from 1972, first for 23:59:59 June 30,
      # second for 23:59:59 December 31. +1 indicates that 23:59:60 follows,
      # -1 indicates that 23:59:59 does not exist, not that the latter has ever occurred.
      # source: https://www.nist.gov/pml/time-and-frequency-division/atomic-standards/leap-second-and-ut1-utc-information
      (+1, +1), # 1972
      (0, +1), # 1973
      (0, +1), # 1974
      (0, +1), # 1975
      (0, +1), # 1976
      (0, +1), # 1977
      (0, +1), # 1978
      (0, +1), # 1979
      (0, 0), # 1980
      (+1, 0), # 1981
      (+1, 0), # 1982
      (+1, 0), # 1983
      (0, 0), # 1984
      (+1, 0), # 1985
      (0, 0), # 1986
      (0, +1), # 1987
      (0, 0), # 1988
      (0, +1), # 1989
      (0, +1), # 1990
      (0, 0), # 1991
      (+1, 0), # 1992
      (+1, 0), # 1993
      (+1, 0), # 1994
      (0, +1), # 1995
      (0, 0), # 1996
      (+1, 0), # 1997
      (0, +1), # 1998
      (0, 0), # 1999
      (0, 0), # 2000
      (0, 0), # 2001
      (0, 0), # 2002
      (0, 0), # 2003
      (0, 0), # 2004
      (0, +1), # 2005
      (0, 0), # 2006
      (0, 0), # 2007
      (0, +1), # 2008
      (0, 0), # 2009
      (0, 0), # 2010
      (0, 0), # 2011
      (+1, 0), # 2012
      (0, 0), # 2013
      (0, 0), # 2014
      (+1, 0), # 2015
      (0, +1), # 2016
      (0, 0),  # 2017
      (0, 0),  # 2018
      (0, 0),  # 2019
      (0, 0),  # 2020
      (0, 0),  # 2021
      (0, 0),  # 2022
    ]

@check_aware_dt('when')
def get_leap_seconds(when) :
    "returns adjustment to be added to UTC at the specified datetime to produce TAI."
    when = when.utctimetuple()
    adj = 10 # as decreed from 1972
    year = leap_seconds_base_year
    while True :
        if year > when.tm_year :
            break
        if year - leap_seconds_base_year >= len(leap_seconds_adjustments) :
            if (
                    when.tm_year - leap_seconds_base_year > len(leap_seconds_adjustments)
                or
                        when.tm_year - leap_seconds_base_year == len(leap_seconds_adjustments)
                    and
                        when.tm_mon > 6
            ) :
                warnings.warn \
                  (
                        "I don't know about leap seconds after %d"
                    %
                        (leap_seconds_base_year + len(leap_seconds_adjustments) - 1)
                  )
            #end if
            break
        #end if
        entry = leap_seconds_adjustments[year - leap_seconds_base_year]
        if year == when.tm_year :
            if when.tm_mon > 6 :
                adj += entry[0]
            #end if
            break
        #end if
        adj += entry[0] + entry[1]
        year += 1
    #end while
    return \
        adj
#end get_leap_seconds

# table of values to add to UT1 to get TT (to date), generated by util/get_delta_t script
delta_t_base_year = 1973
delta_t_base_month = 2
delta_t = \
  [
        [ # 1973
            43.4724, # 2
            43.5648, # 3
            43.6737, # 4
            43.7782, # 5
            43.8763, # 6
            43.9562, # 7
            44.0315, # 8
            44.1132, # 9
            44.1982, # 10
            44.2952, # 11
            44.3936, # 12
        ],
        [ # 1974
            44.4841, # 1
            44.5646, # 2
            44.6425, # 3
            44.7386, # 4
            44.8370, # 5
            44.9302, # 6
            44.9986, # 7
            45.0584, # 8
            45.1284, # 9
            45.2064, # 10
            45.2980, # 11
            45.3897, # 12
        ],
        [ # 1975
            45.4761, # 1
            45.5633, # 2
            45.6450, # 3
            45.7375, # 4
            45.8284, # 5
            45.9133, # 6
            45.9820, # 7
            46.0408, # 8
            46.1067, # 9
            46.1825, # 10
            46.2789, # 11
            46.3713, # 12
        ],
        [ # 1976
            46.4567, # 1
            46.5445, # 2
            46.6311, # 3
            46.7302, # 4
            46.8284, # 5
            46.9247, # 6
            46.9970, # 7
            47.0709, # 8
            47.1451, # 9
            47.2362, # 10
            47.3413, # 11
            47.4319, # 12
        ],
        [ # 1977
            47.5214, # 1
            47.6049, # 2
            47.6837, # 3
            47.7781, # 4
            47.8771, # 5
            47.9687, # 6
            48.0348, # 7
            48.0942, # 8
            48.1608, # 9
            48.2460, # 10
            48.3439, # 11
            48.4355, # 12
        ],
        [ # 1978
            48.5344, # 1
            48.6325, # 2
            48.7294, # 3
            48.8365, # 4
            48.9353, # 5
            49.0319, # 6
            49.1013, # 7
            49.1591, # 8
            49.2286, # 9
            49.3070, # 10
            49.4018, # 11
            49.4945, # 12
        ],
        [ # 1979
            49.5862, # 1
            49.6805, # 2
            49.7602, # 3
            49.8556, # 4
            49.9489, # 5
            50.0347, # 6
            50.1019, # 7
            50.1622, # 8
            50.2260, # 9
            50.2968, # 10
            50.3831, # 11
            50.4599, # 12
        ],
        [ # 1980
            50.5387, # 1
            50.6161, # 2
            50.6866, # 3
            50.7658, # 4
            50.8454, # 5
            50.9187, # 6
            50.9761, # 7
            51.0278, # 8
            51.0843, # 9
            51.1538, # 10
            51.2319, # 11
            51.3063, # 12
        ],
        [ # 1981
            51.3808, # 1
            51.4526, # 2
            51.5160, # 3
            51.5985, # 4
            51.6809, # 5
            51.7573, # 6
            51.8133, # 7
            51.8532, # 8
            51.9014, # 9
            51.9603, # 10
            52.0328, # 11
            52.0985, # 12
        ],
        [ # 1982
            52.1668, # 1
            52.2316, # 2
            52.2938, # 3
            52.3680, # 4
            52.4465, # 5
            52.5180, # 6
            52.5752, # 7
            52.6178, # 8
            52.6668, # 9
            52.7340, # 10
            52.8056, # 11
            52.8792, # 12
        ],
        [ # 1983
            52.9565, # 1
            53.0445, # 2
            53.1268, # 3
            53.2197, # 4
            53.3024, # 5
            53.3747, # 6
            53.4335, # 7
            53.4778, # 8
            53.5300, # 9
            53.5845, # 10
            53.6523, # 11
            53.7256, # 12
        ],
        [ # 1984
            53.7882, # 1
            53.8367, # 2
            53.8830, # 3
            53.9443, # 4
            54.0042, # 5
            54.0536, # 6
            54.0856, # 7
            54.1084, # 8
            54.1463, # 9
            54.1914, # 10
            54.2452, # 11
            54.2958, # 12
        ],
        [ # 1985
            54.3427, # 1
            54.3911, # 2
            54.4320, # 3
            54.4898, # 4
            54.5456, # 5
            54.5977, # 6
            54.6355, # 7
            54.6532, # 8
            54.6776, # 9
            54.7174, # 10
            54.7741, # 11
            54.8253, # 12
        ],
        [ # 1986
            54.8713, # 1
            54.9161, # 2
            54.9581, # 3
            54.9997, # 4
            55.0476, # 5
            55.0912, # 6
            55.1132, # 7
            55.1328, # 8
            55.1532, # 9
            55.1898, # 10
            55.2416, # 11
            55.2838, # 12
        ],
        [ # 1987
            55.3222, # 1
            55.3613, # 2
            55.4063, # 3
            55.4629, # 4
            55.5111, # 5
            55.5524, # 6
            55.5812, # 7
            55.6004, # 8
            55.6262, # 9
            55.6656, # 10
            55.7168, # 11
            55.7698, # 12
        ],
        [ # 1988
            55.8197, # 1
            55.8615, # 2
            55.9130, # 3
            55.9663, # 4
            56.0220, # 5
            56.0700, # 6
            56.0939, # 7
            56.1105, # 8
            56.1314, # 9
            56.1611, # 10
            56.2068, # 11
            56.2583, # 12
        ],
        [ # 1989
            56.3000, # 1
            56.3399, # 2
            56.3790, # 3
            56.4283, # 4
            56.4804, # 5
            56.5352, # 6
            56.5697, # 7
            56.5983, # 8
            56.6328, # 9
            56.6739, # 10
            56.7332, # 11
            56.7972, # 12
        ],
        [ # 1990
            56.8553, # 1
            56.9111, # 2
            56.9755, # 3
            57.0471, # 4
            57.1136, # 5
            57.1738, # 6
            57.2226, # 7
            57.2597, # 8
            57.3073, # 9
            57.3643, # 10
            57.4334, # 11
            57.5016, # 12
        ],
        [ # 1991
            57.5653, # 1
            57.6333, # 2
            57.6973, # 3
            57.7711, # 4
            57.8407, # 5
            57.9058, # 6
            57.9576, # 7
            57.9975, # 8
            58.0426, # 9
            58.1043, # 10
            58.1679, # 11
            58.2389, # 12
        ],
        [ # 1992
            58.3092, # 1
            58.3833, # 2
            58.4537, # 3
            58.5401, # 4
            58.6228, # 5
            58.6917, # 6
            58.7410, # 7
            58.7836, # 8
            58.8406, # 9
            58.8986, # 10
            58.9714, # 11
            59.0438, # 12
        ],
        [ # 1993
            59.1218, # 1
            59.2003, # 2
            59.2747, # 3
            59.3574, # 4
            59.4434, # 5
            59.5242, # 6
            59.5850, # 7
            59.6344, # 8
            59.6928, # 9
            59.7588, # 10
            59.8386, # 11
            59.9111, # 12
        ],
        [ # 1994
            59.9845, # 1
            60.0564, # 2
            60.1231, # 3
            60.2042, # 4
            60.2804, # 5
            60.3530, # 6
            60.4012, # 7
            60.4440, # 8
            60.4900, # 9
            60.5578, # 10
            60.6324, # 11
            60.7059, # 12
        ],
        [ # 1995
            60.7853, # 1
            60.8664, # 2
            60.9387, # 3
            61.0277, # 4
            61.1103, # 5
            61.1870, # 6
            61.2454, # 7
            61.2881, # 8
            61.3378, # 9
            61.4036, # 10
            61.4760, # 11
            61.5525, # 12
        ],
        [ # 1996
            61.6287, # 1
            61.6846, # 2
            61.7433, # 3
            61.8132, # 4
            61.8823, # 5
            61.9497, # 6
            61.9969, # 7
            62.0343, # 8
            62.0714, # 9
            62.1202, # 10
            62.1810, # 11
            62.2382, # 12
        ],
        [ # 1997
            62.2950, # 1
            62.3506, # 2
            62.3995, # 3
            62.4754, # 4
            62.5463, # 5
            62.6136, # 6
            62.6571, # 7
            62.6942, # 8
            62.7383, # 9
            62.7926, # 10
            62.8567, # 11
            62.9146, # 12
        ],
        [ # 1998
            62.9659, # 1
            63.0217, # 2
            63.0807, # 3
            63.1462, # 4
            63.2053, # 5
            63.2599, # 6
            63.2844, # 7
            63.2961, # 8
            63.3126, # 9
            63.3422, # 10
            63.3871, # 11
            63.4339, # 12
        ],
        [ # 1999
            63.4673, # 1
            63.4979, # 2
            63.5319, # 3
            63.5679, # 4
            63.6104, # 5
            63.6444, # 6
            63.6642, # 7
            63.6739, # 8
            63.6926, # 9
            63.7147, # 10
            63.7518, # 11
            63.7927, # 12
        ],
        [ # 2000
            63.8285, # 1
            63.8557, # 2
            63.8804, # 3
            63.9075, # 4
            63.9393, # 5
            63.9691, # 6
            63.9799, # 7
            63.9833, # 8
            63.9938, # 9
            64.0093, # 10
            64.0400, # 11
            64.0670, # 12
        ],
        [ # 2001
            64.0908, # 1
            64.1068, # 2
            64.1282, # 3
            64.1584, # 4
            64.1833, # 5
            64.2094, # 6
            64.2117, # 7
            64.2073, # 8
            64.2116, # 9
            64.2223, # 10
            64.2500, # 11
            64.2761, # 12
        ],
        [ # 2002
            64.2998, # 1
            64.3192, # 2
            64.3450, # 3
            64.3735, # 4
            64.3943, # 5
            64.4151, # 6
            64.4132, # 7
            64.4118, # 8
            64.4097, # 9
            64.4168, # 10
            64.4329, # 11
            64.4511, # 12
        ],
        [ # 2003
            64.4734, # 1
            64.4893, # 2
            64.5053, # 3
            64.5269, # 4
            64.5471, # 5
            64.5597, # 6
            64.5512, # 7
            64.5371, # 8
            64.5359, # 9
            64.5415, # 10
            64.5544, # 11
            64.5654, # 12
        ],
        [ # 2004
            64.5736, # 1
            64.5891, # 2
            64.6015, # 3
            64.6176, # 4
            64.6374, # 5
            64.6549, # 6
            64.6530, # 7
            64.6379, # 8
            64.6372, # 9
            64.6400, # 10
            64.6543, # 11
            64.6723, # 12
        ],
        [ # 2005
            64.6876, # 1
            64.7052, # 2
            64.7313, # 3
            64.7575, # 4
            64.7811, # 5
            64.8001, # 6
            64.7995, # 7
            64.7876, # 8
            64.7831, # 9
            64.7921, # 10
            64.8096, # 11
            64.8311, # 12
        ],
        [ # 2006
            64.8452, # 1
            64.8597, # 2
            64.8850, # 3
            64.9175, # 4
            64.9480, # 5
            64.9794, # 6
            64.9895, # 7
            65.0028, # 8
            65.0138, # 9
            65.0371, # 10
            65.0773, # 11
            65.1122, # 12
        ],
        [ # 2007
            65.1464, # 1
            65.1833, # 2
            65.2145, # 3
            65.2494, # 4
            65.2921, # 5
            65.3279, # 6
            65.3413, # 7
            65.3452, # 8
            65.3496, # 9
            65.3711, # 10
            65.3972, # 11
            65.4296, # 12
        ],
        [ # 2008
            65.4573, # 1
            65.4868, # 2
            65.5152, # 3
            65.5450, # 4
            65.5781, # 5
            65.6127, # 6
            65.6288, # 7
            65.6370, # 8
            65.6493, # 9
            65.6760, # 10
            65.7097, # 11
            65.7461, # 12
        ],
        [ # 2009
            65.7768, # 1
            65.8025, # 2
            65.8237, # 3
            65.8595, # 4
            65.8973, # 5
            65.9323, # 6
            65.9509, # 7
            65.9534, # 8
            65.9628, # 9
            65.9839, # 10
            66.0147, # 11
            66.0420, # 12
        ],
        [ # 2010
            66.0699, # 1
            66.0961, # 2
            66.1310, # 3
            66.1683, # 4
            66.2072, # 5
            66.2356, # 6
            66.2409, # 7
            66.2335, # 8
            66.2349, # 9
            66.2441, # 10
            66.2751, # 11
            66.3054, # 12
        ],
        [ # 2011
            66.3246, # 1
            66.3406, # 2
            66.3624, # 3
            66.3957, # 4
            66.4289, # 5
            66.4619, # 6
            66.4749, # 7
            66.4751, # 8
            66.4829, # 9
            66.5056, # 10
            66.5383, # 11
            66.5706, # 12
        ],
        [ # 2012
            66.6030, # 1
            66.6340, # 2
            66.6569, # 3
            66.6925, # 4
            66.7289, # 5
            66.7579, # 6
            66.7708, # 7
            66.7740, # 8
            66.7846, # 9
            66.8103, # 10
            66.8400, # 11
            66.8779, # 12
        ],
        [ # 2013
            66.9069, # 1
            66.9443, # 2
            66.9763, # 3
            67.0258, # 4
            67.0716, # 5
            67.1100, # 6
            67.1266, # 7
            67.1331, # 8
            67.1458, # 9
            67.1718, # 10
            67.2091, # 11
            67.2460, # 12
        ],
        [ # 2014
            67.2810, # 1
            67.3136, # 2
            67.3457, # 3
            67.3890, # 4
        ],
    ] # delta_t

@check_aware_dt('when')
def get_delta_t(when) :
    "returns a suitable value for delta_t for the given datetime."
    when = when.utctimetuple()
    year, month = when.tm_year, when.tm_mon
    if year < delta_t_base_year :
        year = delta_t_base_year
        month = 1
    elif year == delta_t_base_year :
        month = max(0, month - delta_t_base_month) + 1
    elif year >= delta_t_base_year + len(delta_t) :
        year = delta_t_base_year + len(delta_t) - 1
    #end if
    if year == delta_t_base_year + len(delta_t) - 1 :
        month = min(month, len(delta_t[year - delta_t_base_year]))
    #end if
    return \
        delta_t[year - delta_t_base_year][month - 1]
          # don't bother doing any fancy interpolation
#end get_delta_t

@check_aware_dt('when')
def get_julian_solar_day(when):
    "returns the UT Julian day number (including fraction of a day) corresponding to" \
    " the specified date/time. This version assumes the proleptic Gregorian calendar;" \
    " trying to adjust for pre-Gregorian dates/times seems pointless when the changeover" \
    " happened over such wildly varying times in different regions."
    return \
        (
                (when.timestamp() + get_leap_seconds(when) + tt_offset - get_delta_t(when))
            /
                seconds_per_day
        +
            gregorian_day_offset
        +
            julian_day_offset
        )
#end get_julian_solar_day

@check_aware_dt('when')
def get_julian_ephemeris_day(when) :
    "returns the TT Julian day number (including fraction of a day) corresponding to" \
    " the specified date/time. This version assumes the proleptic Gregorian calendar;" \
    " trying to adjust for pre-Gregorian dates/times seems pointless when the changeover" \
    " happened over such wildly varying times in different regions."
    return \
        (
                (when.timestamp() + get_leap_seconds(when) + tt_offset)
            /
                seconds_per_day
        +
            gregorian_day_offset
        +
            julian_day_offset
        )
#end get_julian_ephemeris_day

def get_julian_century(julian_day):
    return (julian_day - 2451545.0) / 36525.0

def get_julian_ephemeris_century(julian_ephemeris_day):
    return (julian_ephemeris_day - 2451545.0) / 36525.0

def get_julian_ephemeris_millennium(julian_ephemeris_century):
    return (julian_ephemeris_century / 10.0)
